package com.bestcem.xm.member.grpc.client;

import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.label.constant.Constants;
import com.bestcem.xm.member.grpc.client.dto.QdesCascaderOptionDTO;
import com.bestcem.xm.member.grpc.client.dto.QdesProjectDTO;
import com.bestcem.xm.member.grpc.client.dto.QdesQuestionDTO;
import com.bestcem.xm.member.grpc.client.dto.QdesQuestionOptionDTO;
import com.bestcem.xm.qdes.grpc.v1.services.*;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ming.xue <ming.xue@idiaoyan.com>
 * @desc 问卷信息服务
 * @date 2021-08-26
 */
@Slf4j
@Component("xmQdesClient")
public class XmQdesClient {

    /**
     * 问卷信息服务存根
     */
    @GrpcClient(GrpcClientNames.DS_QDES)
    private BaseQdesServiceGrpc.BaseQdesServiceBlockingStub baseStub;

    /**
     * 项目服务
     */
    @GrpcClient(GrpcClientNames.DS_QDES)
    private BpProjectServiceGrpc.BpProjectServiceBlockingStub projectStub;

    /**
     * 获取问卷项目信息
     *
     * @param id
     * @return
     */
    public ServiceResult<QdesProjectDTO> getProject(String id) {
        if (StringUtils.isBlank(id)) {
            return ServiceResult.fail("项目标识不能为空");
        }

        // 获取项目
        ProjectResponse response = baseStub.getProject(GetProjectRequest.newBuilder().setId(id).build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("获取项目失败, response: {}", response);
            return ServiceResult.fail("获取项目失败");
        }
        if (!response.hasProject()) {
            return ServiceResult.fail("项目标识无效");
        }

        Project project = response.getProject();
        QdesProjectDTO projectDTO = this.toQdesProjectDTO(project);
        return ServiceResult.success(projectDTO);
    }

    /**
     * 获取已发布的问题
     *
     * @param projectId
     * @param version
     * @param surveyOrder
     * @return
     */
    public ServiceResult<List<QdesQuestionDTO>> getReleasedProjectQuestions(String projectId, Integer version,
                                                                            Boolean surveyOrder) {
        GetReleasedProjectQuestionsRequest.Builder builder = GetReleasedProjectQuestionsRequest.newBuilder();
        if (StringUtils.isNotBlank(projectId)) {
            builder.setPid(projectId);
        }
        if (version != null) {
            builder.setVersion(version);
        }
        if (surveyOrder != null) {
            builder.setSurveyOrder(surveyOrder);
        }

        // 获取已发布的问题
        GetReleasedProjectQuestionsResponse response = projectStub.getReleasedProjectQuestions(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("获取已发布答卷的问题失败, projectId: {}, version: {}, surveyOrder: {}, response: {}",
                    projectId, version, surveyOrder, response);
            return ServiceResult.fail("获取已发布答卷的问题失败");
        }

        // 返回结果
        List<QuestionInfoList> questions = response.getQuestionsList();
        List<QdesQuestionDTO> questionDTOs = questions.stream().map(this::toQdesQuestionDTO)
                .filter(Objects::nonNull).collect(Collectors.toList());
        return ServiceResult.success(questionDTOs);
    }

    public ServiceResult<List<QdesProjectDTO>> listProject(String orgId, String code) {
        if (StringUtils.isBlank(orgId)) {
            return ServiceResult.fail("【联系人】listProject:orgId不能为空");
        }
        if (StringUtils.isBlank(code)) {
            return ServiceResult.fail("【联系人】listProject:code不能为空");
        }
        // 因貌似不支持search参数，所以将orgId和code组织到project中
        Project project = Project.newBuilder().setCompanyId(orgId).setCode(code).build();
        ListProjectRequest listProjectRequest = ListProjectRequest.newBuilder().setProject(project).build();
        ProjectSearchResponse response = baseStub.listProject(listProjectRequest);
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("【联系人】listProject failed, response: {}", response);
            return ServiceResult.fail("【联系人】listProject failed");
        }
        List<Project> projectListList = response.getProjectListList();
        List<QdesProjectDTO> list = projectListList.stream()
                .filter(Objects::nonNull)
                .map(this::toQdesProjectDTO)
                .collect(Collectors.toList());
        return ServiceResult.success(list);
    }

    /**
     * 类型转换
     *
     * @param question
     * @return
     */
    private QdesQuestionDTO toQdesQuestionDTO(QuestionInfoList question) {
        if (question == null) {
            return null;
        }

        QdesQuestionDTO questionDTO = new QdesQuestionDTO();
        questionDTO.setId(question.getId());
        questionDTO.setType(question.getType());
        questionDTO.setGid(question.getGid());
        questionDTO.setTitle(question.getTitle());
        questionDTO.setCustomQtype(question.getCustomQtype());
        questionDTO.setCid(question.getCid());
        questionDTO.setTags(question.getTagListList());

        List<QdesQuestionOptionDTO> items = question.getItemsList().stream().map(this::toQdesQuestionOptionDTO)
                .filter(Objects::nonNull).collect(Collectors.toList());
        List<QdesQuestionOptionDTO> rowItems = question.getRowItemsList().stream().map(this::toQdesQuestionOptionDTO)
                .filter(Objects::nonNull).collect(Collectors.toList());
        List<QdesCascaderOptionDTO> optionList = question.getOptionListList().stream()
                .map(this::toQdesCascaderOptionDTO).filter(Objects::nonNull).collect(Collectors.toList());
        questionDTO.setItems(items);
        questionDTO.setRowItems(rowItems);
        questionDTO.setOptionList(optionList);
        return questionDTO;
    }

    private QdesCascaderOptionDTO toQdesCascaderOptionDTO(CascaderOption option) {
        if (option == null) {
            return null;
        }

        QdesCascaderOptionDTO optionDTO = new QdesCascaderOptionDTO();
        optionDTO.setGid(option.getGid());
        optionDTO.setTitle(option.getTitle());
        optionDTO.setPid(option.getPid());
        optionDTO.setOoid(option.getOoid());
        return optionDTO;
    }

    private QdesQuestionOptionDTO toQdesQuestionOptionDTO(QuestionOption option) {
        if (option == null) {
            return null;
        }

        QdesQuestionOptionDTO optionDTO = new QdesQuestionOptionDTO();
        optionDTO.setGid(option.getGid());
        optionDTO.setTitle(option.getTitle());
        return optionDTO;
    }

    private QdesProjectDTO toQdesProjectDTO(Project project) {
        QdesProjectDTO projectDTO = new QdesProjectDTO();

        projectDTO.setId(project.getId());
        projectDTO.setCode(project.getCode());
        projectDTO.setTitle(project.getTitle());
        projectDTO.setCreator(project.getCreator());
        projectDTO.setCompanyId(project.getCompanyId());
        projectDTO.setGroupList(project.getGroupListList());
        projectDTO.setVersion(project.getVersion());
        projectDTO.setReleaseVer(project.getReleaseVer());
        projectDTO.setStatus(project.getStatusValue());
        projectDTO.setStructId(project.getStructId());
        projectDTO.setLogicId(project.getLogicId());
        projectDTO.setCustomAttr(project.getCustomAttr());
        projectDTO.setSource(project.getSource());
        projectDTO.setExtId(project.getExtId());
        projectDTO.setTimerExpire(project.getTimerExpire());
        projectDTO.setType(project.getPtypeValue());
        projectDTO.setCopyDemo(project.getIsCopyDemo());
        return projectDTO;
    }
}
